#include "http/znx_http_headers.h"
#include "comm/znx_log.h"

int main()
{
    znx_http_header_t   *header;
    znx_http_headers_t  headers;
    znx_pool_t *pool = znx_pool_create();    
    znx_http_headers_init(&headers);

    znx_http_header_name_t  name;
    znx_str_t               val;

    znx_http_header_name_init(&name, (u_char *)"aAAA", strlen("aAAA"));
    val.data = (u_char *)"1111"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_add(&headers, header);
    znx_http_header_name_init(&name, (u_char *)"AAAA", strlen("AAAA"));
    val.data = (u_char *)"2222"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_add(&headers, header);

    znx_http_header_name_init(&name, (u_char *)"BbBB", strlen("BbBB"));
    val.data = (u_char *)"1111"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_add(&headers, header);
    znx_http_header_name_init(&name, (u_char *)"BBBB", strlen("BBBB"));
    val.data = (u_char *)"2222"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_add(&headers, header);

    znx_http_header_name_init(&name, (u_char *)"CCcC", strlen("CCcC"));
    val.data = (u_char *)"1111"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_add(&headers, header);
    znx_http_header_name_init(&name, (u_char *)"cccc", strlen("cccc"));
    val.data = (u_char *)"2222"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_add(&headers, header);

    znx_http_header_name_init(&name, (u_char *)"DDDD", strlen("DDDD"));
    val.data = (u_char *)"1111"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_add(&headers, header);
    znx_http_header_name_init(&name, (u_char *)"DDDD", strlen("DDDD"));
    val.data = (u_char *)"2222"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_add(&headers, header);

    znx_http_header_name_init(&name, (u_char *)"eeee", strlen("eeee"));
    val.data = (u_char *)"1111"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_add(&headers, header);
    znx_http_header_name_init(&name, (u_char *)"EEEE", strlen("EEEE"));
    val.data = (u_char *)"2222"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_add(&headers, header);

    // get & get_next
    znx_http_header_name_init(&name, (u_char *)"aaaa", strlen("aaaa"));
    header = znx_http_headers_get(&headers, &name, 0);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"1111", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 1111, but got other");
    }
    header = znx_http_headers_get(&headers, &name, 1);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"2222", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2222, but got other");
    }

    znx_http_header_name_init(&name, (u_char *)"bbbb", strlen("bbbb"));
    header = znx_http_headers_get(&headers, &name, 0);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"1111", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 1111, but got other");
    }
    header = znx_http_headers_get(&headers, &name, 1);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"2222", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2222, but got other");
    }

    znx_http_header_name_init(&name, (u_char *)"cccc", strlen("cccc"));
    header = znx_http_headers_get(&headers, &name, 0);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"1111", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 1111, but got other");
    }
    header = znx_http_headers_get(&headers, &name, 1);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"2222", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2222, but got other");
    }

    znx_http_header_name_init(&name, (u_char *)"dddd", strlen("dddd"));
    header = znx_http_headers_get(&headers, &name, 0);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"1111", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 1111, but got other");
    }
    header = znx_http_headers_get(&headers, &name, 1);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"2222", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2222, but got other");
    }

    znx_http_header_name_init(&name, (u_char *)"eeee", strlen("eeee"));
    header = znx_http_headers_get(&headers, &name, 0);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"1111", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 1111, but got other");
    }
    header = znx_http_headers_get(&headers, &name, 1);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"2222", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2222, but got other");
    }

    // set
    znx_http_header_name_init(&name, (u_char *)"CCCC", strlen("CCCC"));
    val.data = (u_char *)"3333"; val.len = znx_strlen(val.data);
    header = znx_pool_calloc(pool, sizeof(znx_http_header_t));
    header->name = name; header->val = val;
    znx_http_headers_set(&headers, header);

    // delete once
    znx_http_header_name_init(&name, (u_char *)"dddd", strlen("dddd"));
    znx_http_headers_del_once(&headers, &name);

    // delete
    znx_http_header_name_init(&name, (u_char *)"bbbb", strlen("bbbb"));
    znx_http_headers_del(&headers, &name);

    // remove non-existent headers
    znx_http_header_name_init(&name, (u_char *)"ffff", strlen("ffff"));
    znx_http_headers_del(&headers, &name);

    // get & get_next
    znx_http_header_name_init(&name, (u_char *)"aaaa", strlen("aaaa"));
    header = znx_http_headers_get(&headers, &name, 0);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"1111", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 1111, but got other");
    }
    header = znx_http_headers_get(&headers, &name, 1);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"2222", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2222, but got other");
    }

    znx_http_header_name_init(&name, (u_char *)"bbbb", strlen("bbbb"));
    header = znx_http_headers_get(&headers, &name, 0);
    if (header != NULL)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect NULL, but got other");
    }

    znx_http_header_name_init(&name, (u_char *)"cccc", strlen("cccc"));
    header = znx_http_headers_get(&headers, &name, 0);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"3333", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 3333, but got other");
    }
    header = znx_http_headers_get(&headers, &name, 1);
    if (header != NULL)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect NULL, but got other");
    }

    znx_http_header_name_init(&name, (u_char *)"dddd", strlen("dddd"));
    header = znx_http_headers_get(&headers, &name, 0);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"2222", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2222, but got other");
    }
    header = znx_http_headers_get(&headers, &name, 1);
    if (header != NULL)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect NULL, but got other");
    }

    znx_http_header_name_init(&name, (u_char *)"eeee", strlen("eeee"));
    header = znx_http_headers_get(&headers, &name, 0);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"1111", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 1111, but got other");
    }
    header = znx_http_headers_get(&headers, &name, 1);
    if (header == NULL ||
        znx_strncmp(header->val.data, (u_char *)"2222", header->val.len) != 0)
    {
        ZNX_DEF_LOG_FATAL(NULL, "expect 2222, but got other");
    }

    // dump headers
    int index = 0;
    znx_queue_t *q = znx_queue_head(&headers.head);
    while (q != &headers.head) {
        header = znx_queue_data(q, znx_http_header_t, queue);
        q = q->next;

        if (index == 0) {
            if (header->name.len != 4 ||
                znx_strcmp(header->name.data, "aAAA") != 0 ||
                header->val.len != 4 ||
                znx_strcmp(header->val.data, "1111") != 0)
            {
                ZNX_DEF_LOG_FATAL(NULL, "expect aAAA: 1111, but got other");
            }
        } else if (index == 1) {
            if (header->name.len != 4 ||
                znx_strcmp(header->name.data, "AAAA") != 0 ||
                header->val.len != 4 ||
                znx_strcmp(header->val.data, "2222") != 0)
            {
                ZNX_DEF_LOG_FATAL(NULL, "expect AAAA: 2222, but got other");
            }
        } else if (index == 2) {
            if (header->name.len != 4 ||
                znx_strcmp(header->name.data, "CCcC") != 0 ||
                header->val.len != 4 ||
                znx_strcmp(header->val.data, "3333") != 0)
            {
                ZNX_DEF_LOG_FATAL(NULL, "expect CCcC: 3333, but got other");
            }
        } else if (index == 3) {
            if (header->name.len != 4 ||
                znx_strcmp(header->name.data, "DDDD") != 0 ||
                header->val.len != 4 ||
                znx_strcmp(header->val.data, "2222") != 0)
            {
                ZNX_DEF_LOG_FATAL(NULL, "expect DDDD: 2222, but got other");
            }
        } else if (index == 4) {
            if (header->name.len != 4 ||
                znx_strcmp(header->name.data, "eeee") != 0 ||
                header->val.len != 4 ||
                znx_strcmp(header->val.data, "1111") != 0)
            {
                ZNX_DEF_LOG_FATAL(NULL, "expect eeee: 1111, but got other");
            }
        }  else if (index == 5) {
            if (header->name.len != 4 ||
                znx_strcmp(header->name.data, "EEEE") != 0 ||
                header->val.len != 4 ||
                znx_strcmp(header->val.data, "2222") != 0)
            {
                ZNX_DEF_LOG_FATAL(NULL, "expect EEEE: 2222, but got other");
            }
        }

        index++;
        
        // It's static global const string, we use '%s' fmt it.
        ZNX_DEF_LOG_DEBUG(NULL, "%s: %s", header->name.data, header->val.data);
    }

    index = 0;
    for ( ;; ) {
        header = znx_http_headers_get_free_hader(&headers);
        if (header == NULL) {
            break;
        }
        index++;
    }

    if (index != 4) {
        ZNX_DEF_LOG_FATAL(NULL, "expect 4, but got other");
    }

    znx_pool_destroy(pool);
}